package com.fxz.common.core.sensitive;

import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import java.io.IOException;
import java.util.List;
import java.util.Objects;

/**
 * 敏感信息脱敏序列化
 *
 * @author fxz
 * @date 2022/4/25
 */
@AllArgsConstructor
@NoArgsConstructor
public class SensitiveInfoSerialize extends JsonSerializer<String> implements ContextualSerializer {

	private SensitiveInfo sensitiveInfo;

	@Override
	public void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
			throws IOException {
		switch (this.sensitiveInfo.value()) {
		case CHINESE_NAME: {
			jsonGenerator.writeString(DesensitizedUtil.chineseName(s));
			break;
		}
		case USER_ID: {
			jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));
			break;
		}
		case PASSWORD: {
			jsonGenerator.writeString(DesensitizedUtil.password(s));
			break;
		}
		case ID_CARD: {
			jsonGenerator.writeString(DesensitizedUtil.idCardNum(s, 6, 2));
			break;
		}
		case FIXED_PHONE: {
			jsonGenerator.writeString(DesensitizedUtil.fixedPhone(s));
			break;
		}
		case MOBILE_PHONE: {
			jsonGenerator.writeString(DesensitizedUtil.mobilePhone(s));
			break;
		}
		case IP: {
			jsonGenerator.writeString(this.ip(s));
			break;
		}
		case ADDRESS: {
			jsonGenerator.writeString(DesensitizedUtil.address(s, 6));
			break;
		}
		case CAR_LICENSE: {
			jsonGenerator.writeString(DesensitizedUtil.carLicense(s));
			break;
		}
		case EMAIL: {
			jsonGenerator.writeString(DesensitizedUtil.email(s));
			break;
		}
		case BANK_CARD: {
			jsonGenerator.writeString(DesensitizedUtil.bankCard(s));
			break;
		}
		case CNAPS_CODE: {
			jsonGenerator.writeString(this.hide(s, 4, 4));
			break;
		}
		case OTHER: {
			jsonGenerator.writeString(this.hide(s, sensitiveInfo.front(), sensitiveInfo.end()));
			break;
		}
		default: {
			jsonGenerator.writeString(s);
		}
		}

	}

	@Override
	public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty)
			throws JsonMappingException {
		// 为空直接跳过
		if (beanProperty != null) {
			// 非String跳过
			if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
				SensitiveInfo sensitiveInfo = beanProperty.getAnnotation(SensitiveInfo.class);
				if (sensitiveInfo == null) {
					sensitiveInfo = beanProperty.getContextAnnotation(SensitiveInfo.class);
				}
				// 如果能得到注解，就将注解的 value 传入
				if (sensitiveInfo != null) {
					// SensitiveInfoSerialize
					return new SensitiveInfoSerialize(sensitiveInfo);
				}
			}
			return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
		}
		return serializerProvider.findNullValueSerializer(null);
	}

	/**
	 * ip脱敏
	 */
	private String ip(String ip) {
		List<String> ipList = StrUtil.split(ip, '.');
		if (ipList.size() < 2) {
			return "*.*.*.*";
		}
		return ipList.get(0) + "." + ipList.get(1) + ".*.*";
	}

	/**
	 * 字段隐藏
	 * @param str 字符串
	 * @param front 前多少位不隐藏
	 * @param end 后多少位不隐藏
	 * @return 处理后的字段
	 */
	private String hide(String str, int front, int end) {
		// 字符串不能为空
		if (StrUtil.isBlank(str)) {
			return StrUtil.EMPTY;
		}
		// 需要截取的不能小于0
		if (front < 0 || end < 0) {
			return StrUtil.EMPTY;
		}
		return StrUtil.hide(str, front, str.length() - end);
	}

}
